﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HHMMS.WorkFlow.Model;
using HHMMS.WorkFlow.Service;
using Bingosoft.RestService.Attributes;

namespace HHMMS.WorkFlow
{
    /// <summary>
    /// 工作流API。
    /// </summary>
    [Service("WFAPI")]
    public class WFAPI
    {
        #region 字段属性
        /// <summary>
        /// 工作流创建、运行成功、作废后触发的事件。
        /// </summary>
        public event WorkflowExecuteEventHandler WorkflowExecute;

        /// <summary>
        /// 获取当前工作流定义。
        /// </summary>
        public WorkflowDefinition CurrentWorkflow { get; private set; }

        /// <summary>
        /// 获取当前的流程实例。
        /// </summary>
        public WorkflowInstance CurrentInstance { get; private set; }

        /// <summary>
        /// 获取当前的任务对于的活动。
        /// </summary>
        public WorkflowActivity CurrentActivity { get; private set; }

        /// <summary>
        /// 获取当前工作项。
        /// </summary>
        public WorkflowItem CurrentWorkItem { get; private set; }
        #endregion

        #region 公开方法
        /// <summary>
        /// 初始化工作流API，用于创建流程实例。
        /// </summary>
        /// <param name="workflowId"></param>
        public void Load(int workflowId)
        {
            this.CurrentInstance = new WorkflowInstance() { InstanceStatus = -1 };
            this.CurrentWorkItem = new WorkflowItem() { WorkItemStatus = -1 };

            this.CurrentWorkflow = WorkflowDefinitionService.Instance.Single(workflowId);
            this.CurrentActivity = WorkflowActivityService.Instance.GetStartActivity(workflowId);
            

        }

        /// <summary>
        /// 初始化工作流API，用于运行工作流。
        /// </summary>
        /// <param name="instanceId"></param>
        /// <param name="taskId"></param>
        public void Load(string instanceId, int taskId)
        {
            this.CurrentInstance = WorkflowInstanceService.Instance.Single(instanceId);
            this.CurrentWorkItem = WorkflowItemService.Instance.Single(instanceId, taskId);

            this.CurrentWorkflow = WorkflowDefinitionService.Instance.Single(this.CurrentInstance.WorkflowId.Value);
            this.CurrentActivity = WorkflowActivityService.Instance.Single(this.CurrentInstance.WorkflowId.Value, this.CurrentWorkItem.ActivityId.Value);
        }

        /// <summary>
        /// 触发WorkflowExecute事件。
        /// </summary>
        /// <param name="e"></param>
        protected void OnWorkflowExecute(WorkflowEventArgs e)
        {
            if (this.WorkflowExecute != null)
            {
                this.WorkflowExecute(this, e);
            }
        }

        /// <summary>
        /// 创建流程实例。
        /// </summary>
        /// <param name="instanceName">实例名称</param>
        /// <param name="dataKey">关联的业务数据主键</param>
        /// <param name="partChoice">审批结果</param>
        /// <param name="partComment">审批意见</param>
        public void Save(string instanceName, string dataKey, string partChoice = null, string partComment = null)
        {
            if (this.CurrentInstance == null || this.CurrentInstance.InstanceStatus < 0)
            {
                //创建新流程
                var instanceId = WorkflowInstanceService.Instance.CreateInstance(this.CurrentWorkflow.WorkflowId.Value, instanceName, dataKey, Bingosoft.Security.SecurityContext.User.Id, partComment);
                if (!string.IsNullOrEmpty(instanceId))
                {
                    this.Load(instanceId, 1);
                    WorkflowEventArgs e = new WorkflowEventArgs() { Activity = this.CurrentActivity, Instance = this.CurrentInstance };
                    this.OnWorkflowExecute(e);
                }
            }
            else
            {
                //编辑状态下只保存流程标题以及意见
                this.CurrentInstance.InstanceName = instanceName;
                WorkflowInstanceService.Instance.Update(this.CurrentInstance);

                this.CurrentWorkItem.PartChoice = partChoice;
                this.CurrentWorkItem.PartComment = partComment;
                WorkflowItemService.Instance.Update(this.CurrentWorkItem);
            }
        }

        /// <summary>
        /// 运行流程到下一环节。
        /// </summary>
        /// <param name="partIds">参与者ID</param>
        /// <param name="partChoice">审批结果</param>
        /// <param name="partComment">审批意见</param>
        public void Run(string partIds, string partChoice, string partComment)
        {
            var activityId = WorkflowInstanceService.Instance.RunInstance(this.CurrentInstance.InstanceId, this.CurrentWorkItem.TaskId.Value, partIds, partChoice, partComment);
            if (activityId > 0)
            {
                var activity = WorkflowActivityService.Instance.Single(this.CurrentWorkflow.WorkflowId.Value, activityId);
                if (activity != null)
                {
                    this.CurrentInstance = WorkflowInstanceService.Instance.Single(this.CurrentInstance.InstanceId);
                    WorkflowEventArgs e = new WorkflowEventArgs() { Activity = activity, Instance = this.CurrentInstance };
                    this.OnWorkflowExecute(e);
                }
            }
        }

        /// <summary>
        /// 作废流程。
        /// </summary>
        /// <param name="partComment">作废原因</param>
        public void Discard(string partComment)
        {
            WorkflowInstanceService.Instance.DiscardInstance(this.CurrentInstance.InstanceId, this.CurrentWorkItem.TaskId.Value, partComment);
            this.CurrentInstance = WorkflowInstanceService.Instance.Single(this.CurrentInstance.InstanceId);
            WorkflowEventArgs e = new WorkflowEventArgs() { Instance = this.CurrentInstance };
            this.OnWorkflowExecute(e);
        }

        /// <summary>
        /// 获取审批结果选择项。
        /// </summary>
        /// <returns></returns>
        public IList<string> GetPartChoices()
        {
            var options = this.CurrentActivity.Options;
            if (!string.IsNullOrEmpty(options))
            {
                return options.Split(',').ToList();
            }
            return null;
        }
        #endregion

        #region 服务方法
        /// <summary>
        /// 获取指定环节的下一环节。
        /// </summary>
        /// <param name="workflowId"></param>
        /// <param name="activityId"></param>
        /// <param name="choice"></param>
        /// <returns></returns>
        [ServiceMethod]
        public IList<WorkflowActivity> GetNextAvtivities(int workflowId, int activityId, string choice)
        {
            var nextActivities = new List<WorkflowActivity>();

            var currentActi = WorkflowActivityService.Instance.Single(workflowId, activityId);
            if (currentActi == null)
                return nextActivities;

            var index = 0;
            if (!string.IsNullOrEmpty(currentActi.Options))
            {
                index = currentActi.Options.Split(',').ToList().FindIndex(item => { return item == choice; });
            }

            if (!string.IsNullOrEmpty(currentActi.OptionActivityId))
            {
                var idsArr = currentActi.OptionActivityId.Split(',');
                if (index > -1 && idsArr.Length > index)
                {
                    var ids = idsArr[index].Split('$');
                    foreach (string str in ids)
                    {
                        var id = str.ConvertTo<int>();
                        if (id > 0)
                        {
                            nextActivities.Add(WorkflowActivityService.Instance.Single(workflowId, id));
                        }
                    }
                }
            }

            return nextActivities;
        }

        /// <summary>
        /// 获取指定环节的参与者。
        /// </summary>
        /// <param name="workflowId">流程ID</param>
        /// <param name="activityId">环节ID</param>
        /// <returns></returns>
        [ServiceMethod]
        public IList<Participant> GetParticipant(int workflowId, int activityId)
        {
            var result = new List<Participant>();
            var currentActi = WorkflowActivityService.Instance.Single(workflowId, activityId);
            if (currentActi == null)
                return result;

            if (currentActi.ParticipantType == 1)
            {
                var users = ParticipantService.Instance.GetUsresByRoleId(currentActi.ParticipantValue);
                if (users != null)
                {
                    result = users.Select(item => { return new Participant() { DeptId = item.DeptId, DeptName = item.DeptName }; }).ToList();
                    result.ForEach(dept =>
                    {
                        dept.Users = users.Where(user => { return user.DeptId.ToLower() == dept.DeptId; }).ToList();
                    });
                }
            }

            return result;
        }

        /// <summary>
        /// 以树节点的形式返回环节的参与者信息。
        /// </summary>
        /// <param name="workflowId"></param>
        /// <param name="activityId"></param>
        /// <returns></returns>
        [ServiceMethod]
        public Object GetParticipantTree(int workflowId, int activityId)
        {
            var result = this.GetParticipant(workflowId, activityId);
            if (result == null) 
                return null;

            return result.Select(item =>
            {
                return new
                {
                    id = item.DeptId,
                    text = item.DeptName,
                    isExpand = true,
                    type = 1,
                    childNodes = item.Users.Select(user =>
                    {
                        return new
                        {
                            id = user.UserId,
                            text = user.UserName,
                            isExpand = true,
                            type = 2
                        };
                    })
                };
            });
        }

        /// <summary>
        /// 设置指定任务为已读。
        /// </summary>
        /// <param name="instanceId"></param>
        /// <param name="taskId"></param>
        /// <returns></returns>
        [ServiceMethod]
        public int SetReadTime(string instanceId, int taskId)
        {
            WorkflowItemService.Instance.SetReadTime(instanceId, taskId);
            return 1;
        }
        #endregion
    }

    /// <summary>
    /// 为WorkflowExecute事件提供委托。
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void WorkflowExecuteEventHandler(object sender, WorkflowEventArgs e);

    /// <summary>
    /// 为WorkflowExecute事件提供参数。
    /// </summary>
    public class WorkflowEventArgs : EventArgs
    {
        /// <summary>
        /// 表示流程的当前环节。
        /// </summary>
        public WorkflowActivity Activity { get; set; }

        /// <summary>
        /// 表示当前的流程实例。
        /// </summary>
        public WorkflowInstance Instance { get; set; }

        public WorkflowEventArgs() { }

        public WorkflowEventArgs(WorkflowActivity activity, WorkflowInstance instance)
        {
            this.Activity = activity;
            this.Instance = instance;
        }
    }
}
